var KOC = require("koc.common.utils");

var Config = require("../../config");
var CommonUtils = require("../common-utils");

var Redis = null;

module.exports = {
    //region 初始化
    Init: function (redis) {
        Redis = redis;
        return this;
    },
    //endregion
    //region GiftHeadline
    GiftHeadline: {
        Key: "GiftHeadline",
        Watch: function (callback) {
            Redis.watch(this.Key, function (err) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                }
                callback(retValue);
            });
        },
        Set: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                User_ID: -1,
                User_NickName: null,
                Anchor_ID: -1,
                Anchor_NickName: null,
                GiftNum: 0,
                GiftAmt: 0,
                GiftInfo: null,
                GuardTime: 0
            }, Value);
            Value.User_ID = KOC.StringUtils.ToIntPositive(Value.User_ID);
            if (Value.User_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            if (!Value.User_NickName) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_NickName]"
                }));
                return;
            }
            Value.Anchor_ID = KOC.StringUtils.ToIntPositive(Value.Anchor_ID);
            if (Value.Anchor_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[Anchor_ID]"
                }));
                return;
            }
            if (!Value.Anchor_NickName) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[Anchor_NickName]"
                }));
                return;
            }
            Value.GiftNum = KOC.StringUtils.ToIntPositive(Value.GiftNum);
            if (Value.GiftNum <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[GiftNum]"
                }));
                return;
            }
            Value.GiftInfo = JSON.stringify(Value.GiftInfo);
            if (!Value.GiftInfo) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[GiftInfo]"
                }));
                return;
            }
            Value.CreateDate = new Date();
            Value.GuardTime = KOC.StringUtils.ToIntPositive(Value.GuardTime) * 60;
            Value.GuardDate = KOC.Moment(Value.CreateDate).add(Value.GuardTime, "seconds");
            RedisMulti.hmset(this.Key, Value);
            callback(KOC.ReturnValue.New());
        },
        Get: function (callback) {
            Redis.hgetall(this.Key, function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                if (Object.keys(result).length) {
                    retValue.returnObject = {
                        User_ID: KOC.StringUtils.ToIntPositive(result.User_ID),
                        User_NickName: result.User_NickName,
                        Anchor_ID: KOC.StringUtils.ToIntPositive(result.Anchor_ID),
                        Anchor_NickName: result.Anchor_NickName,
                        GiftNum: KOC.StringUtils.ToIntPositive(result.GiftNum),
                        GiftAmt: KOC.StringUtils.ToIntPositive(result.GiftAmt),
                        GiftInfo: result.GiftInfo ? JSON.parse(result.GiftInfo) : null,
                        GuardTime: KOC.StringUtils.ToIntPositive(result.GuardTime),
                        GuardDate: new Date(result.GuardDate),
                        CreateDate: new Date(result.CreateDate)
                    };
                    retValue.returnObject.GuardTime_Left = KOC.StringUtils.ToIntPositive(retValue.returnObject.GuardTime - KOC.Moment().diff(KOC.Moment(retValue.returnObject.CreateDate), "seconds"));
                }
                callback(retValue);
            });
        }
    },
    //endregion
    //region UserInfo
    UserInfo: {
        Key: function (User_ID) {
            return "UserInfo:" + User_ID;
        },
        Set: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                User_ID: null,
                NickName: null,
                Sex: -1,
                Pomelo: 0,
                EXP: 0,
                EXP_Next: 0,
                EXP_Difference: 0,
                Level: 0,
                Level_Name: "",
                Level_Next: 0,
                Level_Next_Name: "",
                VIP: false,
                VIP_Expire: null,
                Coin: 0,
                Beans: 0,
                IsAnchor: false,
                IsFamily: false,
                IsAdmin: false,
                IsPhone: false,
                EmblemList: ""
            }, Value);
            Value.VIP = !!Value.VIP;
            Value.IsAnchor = !!Value.IsAnchor;
            Value.IsFamily = !!Value.IsFamily;
            Value.IsAdmin = !!Value.IsAdmin;
            Value.IsPhone = !!Value.IsPhone;
            Value.User_ID = KOC.StringUtils.ToIntPositive(Value.User_ID);
            if (Value.User_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            if (!Value.NickName) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[NickName]"
                }));
                return;
            }
            RedisMulti.hmset(this.Key(Value.User_ID), Value);
            callback(KOC.ReturnValue.New());
        },
        Update: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                User_ID: null,
                NickName: null,
                Sex: null,
                Pomelo: null,
                EXP: null,
                VIP: null,
                VIP_Expire: null,
                Coin: null,
                Beans: null,
                IsAnchor: null,
                IsFamily: null,
                IsAdmin: null
            }, Value);
            Value.User_ID = KOC.StringUtils.ToIntPositive(Value.User_ID);
            if (Value.User_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            var _Key = this.Key(Value.User_ID);
            if (Value.NickName) {
                RedisMulti.hset(_Key, "NickName", Value.NickName);
            }
            if (Value.Sex) {
                RedisMulti.hset(_Key, "Sex", Value.Sex);
            }
            if (Value.Pomelo != undefined) {
                RedisMulti.hset(_Key, "Pomelo", KOC.StringUtils.ToIntPositive(Value.Pomelo));
            }
            if (Value.EXP != undefined) {
                var _LevelInfo = CommonUtils.User.Level.fnLevelInfo(KOC.StringUtils.ToIntPositive(Value.EXP));
                RedisMulti.hset(_Key, "EXP", _LevelInfo.EXP);
                RedisMulti.hset(_Key, "EXP_Next", _LevelInfo.EXP_Next);
                RedisMulti.hset(_Key, "EXP_Difference", _LevelInfo.Difference);
                RedisMulti.hset(_Key, "Level", _LevelInfo.Level);
                RedisMulti.hset(_Key, "Level_Name", _LevelInfo.Level_Name);
                RedisMulti.hset(_Key, "Level_Next", _LevelInfo.Level_Next);
                RedisMulti.hset(_Key, "Level_Next_Name", _LevelInfo.Level_Next_Name);
            }
            if (Value.VIP != undefined) {
                Value.VIP = !!Value.VIP;
                RedisMulti.hset(_Key, "VIP", Value.VIP);
                RedisMulti.hset(_Key, "VIP_Expire", Value.VIP_Expire);
            }
            if (Value.Coin != undefined) {
                RedisMulti.hset(_Key, "Coin", KOC.StringUtils.ToIntPositive(Value.Coin));
            }
            if (Value.Beans != undefined) {
                RedisMulti.hset(_Key, "Beans", KOC.StringUtils.ToIntPositive(Value.Beans));
            }
            if (Value.IsAnchor != undefined) {
                Value.IsAnchor = !!Value.IsAnchor;
                RedisMulti.hset(_Key, "IsAnchor", Value.IsAnchor);
            }
            if (Value.IsFamily != undefined) {
                Value.IsFamily = !!Value.IsFamily;
                RedisMulti.hset(_Key, "IsFamily", Value.IsFamily);
            }
            if (Value.IsAdmin != undefined) {
                Value.IsAdmin = !!Value.IsAdmin;
                RedisMulti.hset(_Key, "IsAdmin", Value.IsAdmin);
            }
            callback(KOC.ReturnValue.New());
        },
        Get: function (User_ID, callback) {
            Redis.hgetall(this.Key(User_ID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                if (!Object.keys(result).length) {
                    retValue.hasError = true;
                    retValue.message = "没找到key[UserInfo]";
                    callback(retValue);
                    return;
                }
                retValue.returnObject = {
                    User_ID: KOC.StringUtils.ToIntPositive(result.User_ID),
                    NickName: result.NickName,
                    Sex: KOC.StringUtils.ToIntPositive(result.Sex),
                    Pomelo: KOC.StringUtils.ToIntPositive(result.Pomelo),
                    EXP: KOC.StringUtils.ToIntPositive(result.EXP),
                    EXP_Next: KOC.StringUtils.ToIntPositive(result.EXP_Next),
                    EXP_Difference: KOC.StringUtils.ToIntPositive(result.EXP_Difference),
                    Level: KOC.StringUtils.ToIntPositive(result.Level),
                    Level_Name: result.Level_Name,
                    Level_Next: KOC.StringUtils.ToIntPositive(result.Level_Next),
                    Level_Next_Name: result.Level_Next_Name,
                    VIP: KOC.StringUtils.ToBoolean(result.VIP),
                    VIP_Expire: result.VIP_Expire ? new Date(result.VIP_Expire) : null,
                    VIP_ExpireDay: 0,
                    Coin: KOC.StringUtils.ToIntPositive(result.Coin),
                    Beans: KOC.StringUtils.ToIntPositive(result.Beans),
                    IsAnchor: KOC.StringUtils.ToBoolean(result.IsAnchor),
                    IsFamily: KOC.StringUtils.ToBoolean(result.IsFamily),
                    IsAdmin: KOC.StringUtils.ToBoolean(result.IsAdmin),
                    IsPhone: KOC.StringUtils.ToBoolean(result.IsPhone),
                    EmblemList: result.EmblemList ? JSON.parse(result.EmblemList) : ""
                };
                if (retValue.returnObject.VIP && retValue.returnObject.VIP_Expire && KOC.Moment().isAfter(KOC.Moment(retValue.returnObject.VIP_Expire))) {
                    retValue.returnObject.VIP = false;
                }
                if (retValue.returnObject.VIP && retValue.returnObject.VIP_Expire) {
                    retValue.returnObject.VIP_ExpireDay = KOC.Moment(retValue.returnObject.VIP_Expire).diff(KOC.Moment(), "days") < 0 ? 0 : KOC.Moment(retValue.returnObject.VIP_Expire).diff(KOC.Moment(), "days");
                }
                callback(retValue);
            });
        },
        Del: function (RedisMulti, User_ID, callback) {
            User_ID = KOC.StringUtils.ToIntPositive(User_ID);
            if (User_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            RedisMulti.del(this.Key(User_ID));
            callback(KOC.ReturnValue.New());
        }
    },
    //endregion
    //region RoomInfo
    RoomInfo: {
        Key: function (RoomID) {
            return "RoomInfo:" + RoomID;
        },
        Watch: function (RoomID, callback) {
            Redis.watch(this.Key(RoomID), function (err) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                }
                callback(retValue);
            });
        },
        Exists: function (RoomID, callback) {
            Redis.exists(this.Key(RoomID), function (err, exists) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                } else {
                    retValue.returnObject = !!exists;
                }
                callback(retValue);
            });
        },
        Set: function (RedisMulti, Value, callback) {
            var Value = {
                RoomID: KOC.StringUtils.ToIntPositive(Value.RoomID),
                Live: false, //直播中
                Live_Title: Value.RoomTitle, //直播主题
                Live_Notice: Value.RoomNotice, //直播公告
                Live_Code: "ROOM_" + Value.RoomID + "_" + KOC.StringUtils.MD5(Value.RoomID + '-' + new Date()), //直播码
                Live_Order_No: null, //直播单号
                Live_CreateDate: null, //直播开始时间
                Live_SocketID: null, //直播SocketID
                Live_IsMobile: false, //是否手机直播
                Live_Mode: 0 //直播模式 0:默认PC直播模式 11:手机直播(竖屏) 12:手机直播(横屏)
            };
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            RedisMulti.hmset(this.Key(Value.RoomID), Value);
            callback(KOC.ReturnValue.New({
                returnObject: Value
            }));
        },
        Set_Live: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                Order_No: null,
                SocketID: null,
                IsMobile: null,
                Mode: null,
                RoomTitle: null,
                RoomNotice: null
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!Value.Order_No) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[Order_No]"
                }));
                return;
            }
            if (!Value.SocketID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[SocketID]"
                }));
                return;
            }
            var _Key = this.Key(Value.RoomID);
            RedisMulti.hset(_Key, "Live", true);
            RedisMulti.hset(_Key, "Live_Title", Value.RoomTitle);
            RedisMulti.hset(_Key, "Live_Notice", Value.RoomNotice);
            RedisMulti.hset(_Key, "Live_Order_No", Value.Order_No);
            RedisMulti.hset(_Key, "Live_CreateDate", new Date());
            RedisMulti.hset(_Key, "Live_SocketID", Value.SocketID);
            RedisMulti.hset(_Key, "Live_IsMobile", !!Value.IsMobile);
            RedisMulti.hset(_Key, "Live_Mode", KOC.StringUtils.ToIntPositive(Value.Mode));
            callback(KOC.ReturnValue.New());
        },
        Set_LiveEnd: function (RedisMulti, RoomID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            var _Key = this.Key(RoomID);
            RedisMulti.hset(_Key, "Live", false);
            RedisMulti.hset(_Key, "Live_Code", "ROOM_" + RoomID + "_" + KOC.StringUtils.MD5(RoomID + '-' + new Date()));
            RedisMulti.hset(_Key, "Live_Order_No", null);
            RedisMulti.hset(_Key, "Live_CreateDate", null);
            RedisMulti.hset(_Key, "Live_SocketID", null);
            RedisMulti.hset(_Key, "Live_IsMobile", false);
            RedisMulti.hset(_Key, "Live_Mode", 0);
            callback(KOC.ReturnValue.New());
        },
        Get: function (RoomID, callback) {
            Redis.hgetall(this.Key(RoomID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                if (!Object.keys(result).length) {
                    retValue.hasError = true;
                    retValue.message = "没找到key[RoomInfo]";
                    callback(retValue);
                    return;
                }
                retValue.returnObject = {
                    RoomID: KOC.StringUtils.ToIntPositive(result.RoomID),
                    Live: KOC.StringUtils.ToBoolean(result.Live),
                    Live_Code: result.Live_Code,
                    Live_Title: result.Live_Title,
                    Live_Notice: result.Live_Notice,
                    Live_Order_No: result.Live_Order_No || null,
                    Live_CreateDate: result.Live_CreateDate ? new Date(result.Live_CreateDate) : null,
                    Live_SocketID: result.Live_SocketID || null,
                    Live_IsMobile: KOC.StringUtils.ToBoolean(result.Live_IsMobile),
                    Live_Mode: KOC.StringUtils.ToInt(result.Live_Mode)
                };
                var _MediaCDN = Config.Common.MediaCDN[Config.Common.MediaCDN.Current];
                retValue.returnObject.Live_URL = _MediaCDN.PULL.replace("{LIVECODE}", retValue.returnObject.Live_Code);
                retValue.returnObject.Live_PUSH = _MediaCDN.PUSH;
                callback(retValue);
            });
        }
    },
    //endregion
    //region Room_AnchorInfo
    Room_AnchorInfo: {
        Key: function (RoomID) {
            return "Room-AnchorInfo:" + RoomID;
        },
        Set: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                RoomName: null,
                RoomWelcome: null,
                NickName: null,
                Birthday: null,
                Constellation: null,
                Beans: 0,
                Pomelo: 0,
                EXP: 0,
                EXP_Next: 0,
                EXP_Difference: 0,
                Level: 0,
                Level_Name: "",
                Level_Next: 0,
                Level_Next_Name: "",
                Tags: "",
                Fans: 0,
                Attention: 0,
                Family_ID: null,
                EmblemList: ""
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            RedisMulti.hmset(this.Key(Value.RoomID), Value);
            callback(KOC.ReturnValue.New());
        },
        Update: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                RoomName: null,
                RoomWelcome: null,
                NickName: null,
                Birthday: null,
                Constellation: null,
                Pomelo: null,
                EXP: null,
                EXP_Next: null,
                EXP_Difference: null,
                Level: null,
                Level_Name: null,
                Level_Next: null,
                Level_Next_Name: null,
                Tags: null,
                Fans: null,
                Attention: null,
                Family_ID: null,
                EmblemList: null
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            var _Key = this.Key(Value.RoomID);
            if (Value.RoomName) {
                RedisMulti.hset(_Key, "RoomName", Value.RoomName);
            }
            if (Value.RoomWelcome) {
                RedisMulti.hset(_Key, "RoomWelcome", Value.RoomWelcome);
            }
            if (Value.NickName) {
                RedisMulti.hset(_Key, "NickName", Value.NickName);
            }
            if (Value.Birthday) {
                RedisMulti.hset(_Key, "Birthday", Value.Birthday);
            }
            if (Value.Constellation) {
                RedisMulti.hset(_Key, "Constellation", Value.Constellation);
            }
            if (Value.Beans != undefined) {
                RedisMulti.hset(_Key, "Beans", KOC.StringUtils.ToIntPositive(Value.Beans));
            }
            if (Value.Pomelo != undefined) {
                RedisMulti.hset(_Key, "Pomelo", KOC.StringUtils.ToIntPositive(Value.Pomelo));
            }
            if (Value.EXP != undefined) {
                var _LevelInfo = CommonUtils.Anchor.Level.fnLevelInfo(KOC.StringUtils.ToIntPositive(Value.EXP));
                RedisMulti.hset(_Key, "EXP", _LevelInfo.EXP);
                RedisMulti.hset(_Key, "EXP_Next", _LevelInfo.EXP_Next);
                RedisMulti.hset(_Key, "EXP_Difference", _LevelInfo.Difference);
                RedisMulti.hset(_Key, "Level", _LevelInfo.Level);
                RedisMulti.hset(_Key, "Level_Name", _LevelInfo.Level_Name);
                RedisMulti.hset(_Key, "Level_Next", _LevelInfo.Level_Next);
                RedisMulti.hset(_Key, "Level_Next_Name", _LevelInfo.Level_Next_Name);
            }
            if (Value.Tags != undefined) {
                RedisMulti.hset(_Key, "Tags", Value.Tags);
            }
            if (Value.Fans != undefined) {
                RedisMulti.hset(_Key, "Fans", KOC.StringUtils.ToIntPositive(Value.Fans));
            }
            if (Value.Attention != undefined) {
                RedisMulti.hset(_Key, "Attention", KOC.StringUtils.ToIntPositive(Value.Attention));
            }
            if (Value.Family_ID) {
                Value.Family_ID = KOC.StringUtils.ToIntPositive(Value.Family_ID);
                RedisMulti.hset(_Key, "Family_ID", Value.Family_ID);
            }
            if (Value.EmblemList) {
                RedisMulti.hset(_Key, "EmblemList", Value.EmblemList);
            }
            callback(KOC.ReturnValue.New());
        },
        Get: function (RoomID, callback) {
            Redis.hgetall(this.Key(RoomID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                if (!Object.keys(result).length) {
                    retValue.hasError = true;
                    retValue.message = "没找到key[Room_AnchorInfo]";
                    callback(retValue);
                    return;
                }
                retValue.returnObject = {
                    RoomID: KOC.StringUtils.ToIntPositive(result.RoomID),
                    RoomName: result.RoomName || null,
                    RoomWelcome: result.RoomWelcome,
                    NickName: result.NickName,
                    Birthday: result.Birthday ? new Date(result.Birthday) : null,
                    Constellation: result.Constellation,
                    Beans: KOC.StringUtils.ToIntPositive(result.Beans),
                    Pomelo: KOC.StringUtils.ToIntPositive(result.Pomelo),
                    EXP: KOC.StringUtils.ToIntPositive(result.EXP),
                    EXP_Next: KOC.StringUtils.ToIntPositive(result.EXP_Next),
                    EXP_Difference: KOC.StringUtils.ToIntPositive(result.EXP_Difference),
                    Level: KOC.StringUtils.ToIntPositive(result.Level),
                    Level_Name: result.Level_Name,
                    Level_Next: KOC.StringUtils.ToIntPositive(result.Level_Next),
                    Level_Next_Name: result.Level_Next_Name,
                    Tags: result.Tags ? String(result.Tags).split(",") : null,
                    Fans: KOC.StringUtils.ToIntPositive(result.Fans),
                    Attention: KOC.StringUtils.ToIntPositive(result.Attention),
                    Family_ID: KOC.StringUtils.ToIntPositive(result.Family_ID) || null,
                    EmblemList: result.EmblemList ? JSON.parse(result.EmblemList) : null
                };
                callback(retValue);
            });
        }
    },
    //endregion
    //region Room_UserList
    Room_UserList: {
        Key: function (RoomID) {
            return "Room-UserList:" + RoomID;
        },
        Add: function (RedisMulti, RoomID, User_ID, Score, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            Score = KOC.StringUtils.ToIntPositive(Score);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            RedisMulti.zadd(this.Key(RoomID), Score, User_ID);
            callback(KOC.ReturnValue.New());
        },
        Remove: function (RedisMulti, RoomID, User_ID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            RedisMulti.zrem(this.Key(RoomID), User_ID);
            callback(KOC.ReturnValue.New());
        },
        Get: function (Value, callback) {
            if (typeof Value === "number") {
                Value = {
                    RoomID: Value
                };
            }
            Value = KOC.Lodash.extend({
                RoomID: null,
                Start: null,
                Length: null
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            Value.Start = KOC.StringUtils.ToIntPositive(Value.Start);
            Value.Length = KOC.StringUtils.ToIntPositive(Value.Length) || 300;
            Value.Length = Value.Length > 300 ? 300 : Value.Length; //最多取默认300条
            Redis.zrevrange(this.Key(Value.RoomID), Value.Start, Value.Start + Value.Length - 1, function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = result;
                callback(retValue);
            });
        }
    },
    //endregion
    //region Room_UserInfo
    Room_UserInfo: {
        Key: function (RoomID, User_ID) {
            return "Room-UserInfo:" + RoomID + ":" + User_ID;
        },
        Set: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                Guest: false,
                User_ID: null,
                NickName: null,
                Anchor: false,
                Admin: false,
                Guardian: false,
                Guardian_Mode: null,
                Guardian_Expire: null,
                Black: false,
                Black_Shutup_Expire: null,
                SocketID: null,
                EmblemList: null
            }, Value);
            Value.GiftLast_ID = -1;
            Value.GiftLast_UserID = -1;
            Value.GiftLast_Num = 0;
            Value.GiftLast_Count = 0;
            Value.GiftLast_Date = null;
            Value.Guest = !!Value.Guest;
            Value.Admin = !!Value.Admin;
            Value.Guardian = !!Value.Guardian;
            Value.Black = !!Value.Black;
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!Value.User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            if (!Value.NickName) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[NickName]"
                }));
                return;
            }
            if (!Value.SocketID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[SocketID]"
                }));
                return;
            }
            Value.Anchor = Value.RoomID == KOC.StringUtils.ToIntPositive(Value.User_ID);
            Value.Key = this.Key(Value.RoomID, Value.User_ID);
            RedisMulti.hmset(Value.Key, {
                RoomID: Value.RoomID,
                Guest: Value.Guest,
                User_ID: Value.User_ID,
                NickName: Value.NickName,
                Anchor: Value.Anchor,
                Admin: Value.Admin,
                Guardian: Value.Guardian,
                Guardian_Mode: Value.Guardian_Mode,
                Guardian_Expire: Value.Guardian_Expire,
                Black: Value.Black,
                Black_Shutup_Expire: Value.Black_Shutup_Expire,
                GiftLast_ID: Value.GiftLast_ID,
                GiftLast_UserID: Value.GiftLast_UserID,
                GiftLast_Num: Value.GiftLast_Num,
                GiftLast_Count: Value.GiftLast_Count,
                GiftLast_Date: Value.GiftLast_Date,
                SocketID: Value.SocketID,
                EmblemList: Value.EmblemList ? Value.EmblemList : ""
            });
            callback(KOC.ReturnValue.New());
        },
        Update: function (RedisMulti, Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                User_ID: null,
                Admin: null,
                Guardian: null,
                Guardian_Mode: null,
                Guardian_Expire: null,
                Black: null,
                Black_Shutup_Expire: null,
                GiftLast_ID: null,
                GiftLast_UserID: null,
                GiftLast_Num: null,
                GiftLast_Count: null
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            Value.User_ID = KOC.StringUtils.ToIntPositive(Value.User_ID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            var _Key = this.Key(Value.RoomID, Value.User_ID);
            if (Value.Admin != undefined) {
                Value.Admin = !!Value.Admin;
                RedisMulti.hset(_Key, "Admin", Value.Admin);
            }
            if (Value.Guardian != undefined) {
                Value.Guardian = !!Value.Guardian;
                RedisMulti.hset(_Key, "Guardian", Value.Guardian);
                RedisMulti.hset(_Key, "Guardian_Mode", Value.Guardian_Mode);
                RedisMulti.hset(_Key, "Guardian_Expire", Value.Guardian_Expire);
            }
            if (Value.Black != undefined) {
                Value.Black = !!Value.Black;
                RedisMulti.hset(_Key, "Black", Value.Black);
                RedisMulti.hset(_Key, "Black_Shutup_Expire", Value.Black_Shutup_Expire);
            }
            Value.GiftLast_ID = KOC.StringUtils.ToIntPositive(Value.GiftLast_ID);
            if (Value.GiftLast_ID > 0) {
                RedisMulti.hset(_Key, "GiftLast_ID", KOC.StringUtils.ToIntPositive(Value.GiftLast_ID));
                RedisMulti.hset(_Key, "GiftLast_UserID", KOC.StringUtils.ToIntPositive(Value.GiftLast_UserID));
                RedisMulti.hset(_Key, "GiftLast_Num", KOC.StringUtils.ToIntPositive(Value.GiftLast_Num));
                RedisMulti.hset(_Key, "GiftLast_Count", KOC.StringUtils.ToIntPositive(Value.GiftLast_Count));
                RedisMulti.hset(_Key, "GiftLast_Date", new Date());
            }
            callback(KOC.ReturnValue.New());
        },
        Get: function (RoomID, User_ID, callback) {
            Redis.hgetall(this.Key(RoomID, User_ID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                if (!Object.keys(result).length) {
                    retValue.hasError = true;
                    retValue.message = "没找到key[Room_UserInfo]";
                    callback(retValue);
                    return;
                }
                retValue.returnObject = {
                    RoomID: KOC.StringUtils.ToInt(result.RoomID),
                    Guest: KOC.StringUtils.ToBoolean(result.Guest),
                    User_ID: result.User_ID,
                    NickName: result.NickName,
                    Anchor: KOC.StringUtils.ToBoolean(result.Anchor),
                    Admin: KOC.StringUtils.ToBoolean(result.Admin),
                    Guardian: KOC.StringUtils.ToBoolean(result.Guardian),
                    Guardian_Mode: result.Guardian_Mode,
                    Guardian_Expire: result.Guardian_Expire ? new Date(result.Guardian_Expire) : null,
                    Guardian_ExpireDay: 0,
                    Black: KOC.StringUtils.ToBoolean(result.Black),
                    Black_Shutup_Expire: result.Black_Shutup_Expire ? new Date(result.Black_Shutup_Expire) : null,
                    GiftLast_ID: KOC.StringUtils.ToInt(result.GiftLast_ID, -1),
                    GiftLast_UserID: KOC.StringUtils.ToInt(result.GiftLast_UserID, -1),
                    GiftLast_Num: KOC.StringUtils.ToInt(result.GiftLast_Num),
                    GiftLast_Count: KOC.StringUtils.ToInt(result.GiftLast_Count),
                    GiftLast_Date: result.GiftLast_Date ? new Date(result.GiftLast_Date) : null,
                    SocketID: result.SocketID,
                    EmblemList: result.EmblemList ? JSON.parse(result.EmblemList) : null
                };
                if (!retValue.returnObject.Guest) {
                    retValue.returnObject.User_ID = KOC.StringUtils.ToIntPositive(retValue.returnObject.User_ID);
                }
                if (retValue.returnObject.Guardian && retValue.returnObject.Guardian_Expire && KOC.Moment().isAfter(KOC.Moment(retValue.returnObject.Guardian_Expire))) {
                    retValue.returnObject.Guardian = false;
                }
                if (retValue.returnObject.Guardian && retValue.returnObject.Guardian_Expire) {
                    retValue.returnObject.Guardian_ExpireDay = KOC.Moment(retValue.returnObject.Guardian_Expire).diff(KOC.Moment(), "days") < 0 ? 0 : KOC.Moment(retValue.returnObject.Guardian_Expire).diff(KOC.Moment(), "days");
                }
                if (retValue.returnObject.Black && retValue.returnObject.Black_Shutup_Expire && KOC.Moment().isAfter(KOC.Moment(retValue.returnObject.Black_Shutup_Expire))) {
                    retValue.returnObject.Black = false;
                }
                callback(retValue);
            });
        },
        Del: function (RedisMulti, RoomID, User_ID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            RedisMulti.del(this.Key(RoomID, User_ID));
            callback(KOC.ReturnValue.New());
        }
    },
    //endregion
    //region Room_UserInfo_Socket
    Room_UserInfo_Socket: {
        Key: function (RoomID, User_ID) {
            return "Room-UserInfo-Socket:" + RoomID + ":" + User_ID;
        },
        Watch: function (RoomID, User_ID, callback) {
            Redis.watch(this.Key(RoomID, User_ID), function (err) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                }
                callback(retValue);
            });
        },
        Add: function (RedisMulti, RoomID, User_ID, SocketID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            if (!SocketID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[SocketID]"
                }));
                return;
            }
            RedisMulti.sadd(this.Key(RoomID, User_ID), SocketID);
            callback(KOC.ReturnValue.New());
        },
        Remove: function (RoomID, User_ID, SocketID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            User_ID = KOC.StringUtils.ToIntPositive(User_ID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (User_ID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            if (!SocketID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[SocketID]"
                }));
                return;
            }
            Redis.srem(this.Key(RoomID, User_ID), SocketID);
            callback(KOC.ReturnValue.New());
        },
        Del: function (RedisMulti, RoomID, User_ID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            User_ID = KOC.StringUtils.ToIntPositive(User_ID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            RedisMulti.del(this.Key(RoomID, User_ID));
            callback(KOC.ReturnValue.New());
        },
        Get: function (RoomID, User_ID, callback) {
            Redis.smembers(this.Key(RoomID, User_ID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = result;
                callback(retValue);
            });
        },
        Exists: function (RoomID, User_ID, callback) {
            Redis.exists(this.Key(RoomID, User_ID), function (err, exists) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                } else {
                    retValue.returnObject = !!exists;
                }
                callback(retValue);
            });
        }
    },
    //endregion
    //region Room_GiftPond
    Room_GiftPond: {
        Key: function (RoomID) {
            return "Room-GiftPond:" + RoomID;
        },
        Watch: function (RoomID, callback) {
            Redis.watch(this.Key(RoomID), function (err) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                }
                callback(retValue);
            });
        },
        Reset: function (RedisMulti, RoomID, callback) {
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            RedisMulti.set(this.Key(RoomID), 0);
            callback(KOC.ReturnValue.New());
        },
        Update: function (RoomID, Amt, callback) {
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            Redis.incrby(this.Key(RoomID), Amt, function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                } else {
                    retValue.returnObject = KOC.StringUtils.ToIntPositive(result);
                }
                callback(retValue);
            });
        },
        Get: function (RoomID, callback) {
            Redis.get(this.Key(RoomID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = KOC.StringUtils.ToIntPositive(result);
                callback(retValue);
            });
        }
    },
    //endregion
    //region Room_GiftPond_User
    Room_GiftPond_User: {
        Key: function (RoomID) {
            return "Room-GiftPond-User:" + RoomID;
        },
        Add: function (RoomID, User_ID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            if (!User_ID) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[User_ID]"
                }));
                return;
            }
            Redis.sadd(this.Key(RoomID), User_ID);
            callback(KOC.ReturnValue.New());
        },
        Get: function (RoomID, callback) {
            Redis.smembers(this.Key(RoomID), function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = result;
                callback(retValue);
            });
        },
        Del: function (RedisMulti, RoomID, callback) {
            RoomID = KOC.StringUtils.ToIntPositive(RoomID);
            if (RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            RedisMulti.del(this.Key(RoomID));
            callback(KOC.ReturnValue.New());
        }
    },
    //endregion
    //region Room_GiftFloat
    Room_GiftFloat: {
        Key: function (RoomID) {
            return "Room-GiftFloat:" + RoomID;
        },
        Add: function (Value, callback) {
            Value = KOC.Lodash.extend({
                RoomID: null,
                User_ID: -1,
                User_NickName: null,
                User_ID_Gift: -1,
                User_NickName_Gift: null,
                Duration: 0,
                GiftNum: 0,
                GiftAmt: 0,
                GiftInfo: null
            }, Value);
            Value.RoomID = KOC.StringUtils.ToIntPositive(Value.RoomID);
            if (Value.RoomID <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "参数错误[RoomID]"
                }));
                return;
            }
            var _Data = {
                User_ID: Value.User_ID,
                User_NickName: Value.User_NickName,
                User_ID_Gift: Value.User_ID_Gift,
                User_NickName_Gift: Value.User_NickName_Gift,
                Duration: Value.Duration,
                GiftNum: Value.GiftNum,
                GiftAmt: Value.GiftAmt,
                GiftInfo: Value.GiftInfo,
                CreateDate: new Date()
            };
            Redis.lpush(this.Key(Value.RoomID), JSON.stringify(_Data), function (err) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = _Data;
                callback(retValue);
            });
        },
        Del: function (RoomID, callback) {
            Redis.ltrim(this.Key(RoomID), 0, 9, function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = result;
                callback(retValue);
            });
        },
        Get: function (RoomID, Second, callback) {
            Second = KOC.StringUtils.ToIntPositive(Second);
            if (Second <= 0) {
                callback(KOC.ReturnValue.New({
                    hasError: true,
                    message: "传入参数错误[Second]"
                }));
                return;
            }
            Redis.lrange(this.Key(RoomID), 0, 9, function (err, result) {
                var retValue = KOC.ReturnValue.New();
                if (err) {
                    retValue.hasError = true;
                    retValue.message = err.message;
                    callback(retValue);
                    return;
                }
                retValue.returnObject = [];
                KOC.Lodash.forEach(result, function (ThisValue) {
                    try {
                        ThisValue = JSON.parse(ThisValue);
                    } catch (ex) {
                        return true;
                    }
                    ThisValue.Duration = Second - KOC.Moment().diff(KOC.Moment(new Date(ThisValue.CreateDate)), "seconds");
                    if (ThisValue.Duration > 0) {
                        retValue.returnObject.push(ThisValue);
                    }
                });
                callback(retValue);
            });
        }
    },
    //endregion
    //region Clear
    Clear: function () {
        Redis.flushdb();
    }
    //endregion
};